"use strict";
/**
 * package操作工具类
 */
const path = require("path");
const pathExists = require("path-exists").sync;
const { isObject } = require("@wenjun-cli/utils");
const log = require("@wenjun-cli/log");
const formatPath = require("@wenjun-cli/format-path");
const pkgDir = require("pkg-dir").sync;
const npminstall = require("npminstall");
const fse = require("fs-extra");

const {
  getDefaultRegistry,
  getNpmLatestVersion,
} = require("@wenjun-cli/get-npm-info");

class Package {
  constructor(options) {
    // options不能为空且必须是一个对象
    if (!options) {
      throw new Error("Package类的options参数不能为空！");
    }
    if (!isObject(options)) {
      throw new Error("Package类的options参数必须为对象！");
    }
    // package的目标路径
    this.targetPath = options.targetPath;
    // package的缓存路径
    this.storeDir = options.storeDir;
    // package的name
    this.packageName = options.packageName;
    // package的version
    this.packageVersion = options.packageVersion;
    // package的缓存目录前缀
    this.cacheFilePathPrefix = this.packageName.replace("/", "_");
  }
  // 获取缓存文件路径(js的新语法：动态计算属性）
  get cacheFilePath() {
    return path.resolve(
      this.storeDir,
      `_${this.cacheFilePathPrefix}@${this.packageVersion}@${this.packageName}`
    );
  }
  // 生成npm模块最新版路径的方法
  getSpecificCacheFilePath(packageVersion) {
    return path.resolve(
      this.storeDir,
      `_${this.cacheFilePathPrefix}@${packageVersion}@${this.packageName}`
    );
  }
  // todo 把latest转成具体的版本
  async prepare() {
    if (this.storeDir && !pathExists(this.storeDir)) {
      fse.mkdirpSync(this.storeDir);
    }
    // 拿到当前包的最新版本
    if (this.packageVersion === "latest") {
      this.packageVersion = await getNpmLatestVersion(this.packageName);
    }
  }

  // todo 判断当前package是否存在
  async exists() {
    if (this.storeDir) {
      await this.prepare();
      return pathExists(this.cacheFilePath);
    } else {
      return pathExists(this.targetPath);
    }
  }
  // todo 安装package
  async install() {
    await this.prepare();
    return npminstall({
      root: this.targetPath,
      storeDir: this.storeDir,
      registry: getDefaultRegistry(),
      pkgs: [{ name: this.packageName, version: this.packageVersion }],
    });
  }
  // todo 更新package
  async update() {
    await this.prepare();
    // 1.获取最新的npm模块的版本号
    const latestPackageVersion = await getNpmLatestVersion(this.packageName);
    log.verbose(this.packageName + "版本号：", latestPackageVersion);
    // 2.查询最新版本对应的路径是否存在
    const latestFilePath = this.getSpecificCacheFilePath(latestPackageVersion);
    // 3.如果不存在，则直接安装最新版本
    if (!pathExists(latestFilePath)) {
      await npminstall({
        root: this.targetPath,
        storeDir: this.storeDir,
        registry: getDefaultRegistry(),
        pkgs: [{ name: this.packageName, version: latestPackageVersion }],
      });
      this.packageVersion = latestPackageVersion;
    } else {
      this.packageVersion = latestPackageVersion;
    }
  }
  // 获取入口文件的位置
  getRootFilePath() {
    function _getRootFile(targetPath) {
      // 1.获取package.json所在的目录-pkg-dir
      const dir = pkgDir(targetPath);
      log.verbose("pkgFileDir", dir);
      if (dir) {
        // 2.获取package.json- require
        const pkgFile = require(path.resolve(dir, "package.json"));
        // 3.寻找main/lib - path
        if (pkgFile && pkgFile.main) {
          // 4.路径兼容（macOS/Windows）
          return formatPath(path.resolve(dir, pkgFile.main));
        }
      }
      return null;
    }
    if (this.storeDir) {
      return _getRootFile(this.cacheFilePath);
    } else {
      return _getRootFile(this.targetPath);
    }
  }
}
module.exports = Package;
